package matheus.tp01cg.objetosdedesenho.recorte;

import matheus.tp01cg.objetosdedesenho.Circunferencia;
import matheus.tp01cg.objetosdedesenho.Coords;
import matheus.tp01cg.objetosdedesenho.DesenhoComposto;
import matheus.tp01cg.objetosdedesenho.ObjetoDeDesenho;
import matheus.tp01cg.objetosdedesenho.Poligono;
import matheus.tp01cg.objetosdedesenho.Reta;
import android.util.Log;

/**
 * Classe base para Recorte. Fornece interface para o recorte de reta (que deve
 * ser implementado em uma subclasse) e implementa mecanismos para recorte de
 * qualquer subtipo (conhecido ateh o momento) de ObjetoDeDesenho
 * 
 * @author matheus
 * 
 */
public abstract class Recorte {
	public Coords limMin, limMax;

	public Recorte(Coords limMin, Coords limMax) {
		this.limMin = limMin;
		this.limMax = limMax;
	}

	/**
	 * 
	 * @param reta
	 * @return Uma nova instacia da reta recortada
	 */
	protected abstract Reta recortaReta(Reta reta);

	// private Poligono recortaPoligono(Poligono poligono) {
	// Poligono retorno = poligono.poligonoCreate(poligono.getCorContorno(),
	// poligono.getCorPreenchimento());
	// ArrayList<Reta> listaDeRetas = poligono.criarListaDeRetas();
	// for (int i = 0; i < listaDeRetas.size(); i++) {
	// Reta novaReta = recortaReta(listaDeRetas.get(i));
	// if (!novaReta.nula) {
	// try {
	// retorno.adicionarVertice(novaReta.getPontoInicial());
	// retorno.adicionarVertice(novaReta.getPontoFinal());
	// } catch (Exception e) {
	// Log.d(null, "Excecao lancada em " + getClass().toString()
	// + ".recortaPoligono(Poligono) por "
	// + "retorno.adicionarVertice()", e);
	// }
	// }
	// }
	// return retorno;
	// }

	private Poligono recortaPoligono(Poligono poligono) {
		return SutherlandHodgman.recortaPoligono(poligono, limMin, limMax);
	}

	/**
	 * 
	 * @param circunferencia
	 * @return Uma nova instancia da circunferencia recordate
	 */
	private Circunferencia recortaCircunferencia(Circunferencia circunferencia) {
		Circunferencia retorno = null;
		try {
			retorno = (Circunferencia) circunferencia.clone();
			retorno.setLimMin(limMin);
			retorno.setLimMax(limMax);
		} catch (CloneNotSupportedException e) {
			Log.d(null, "Excecao lancada em " + getClass().toString()
					+ ".recortaCircunferencia(Circunferencia) por "
					+ "circunferencia.clone()", e);
		}
		return retorno;
	}

	private DesenhoComposto recortaDesenhoComposto(
			DesenhoComposto desenhoComposto) {
		DesenhoComposto retorno = new DesenhoComposto();
		for (int i = 0; i < desenhoComposto.listaDeDesenhos.size(); i++) {
			retorno.listaDeDesenhos.add(recorta(desenhoComposto.listaDeDesenhos
					.get(i)));
		}
		return retorno;
	}

	/**
	 * 
	 * @param objetoDeDesenho
	 * @return Uma nova instancia do ObjetoDeDesenho recortado
	 */
	public ObjetoDeDesenho recorta(ObjetoDeDesenho objetoDeDesenho) {
		ObjetoDeDesenho retorno = null;
		if (objetoDeDesenho instanceof Reta) {
			retorno = (ObjetoDeDesenho) recortaReta((Reta) objetoDeDesenho);
		} else if (objetoDeDesenho instanceof Poligono) {
			retorno = (ObjetoDeDesenho) recortaPoligono((Poligono) objetoDeDesenho);
		} else if (objetoDeDesenho instanceof Circunferencia) {
			retorno = (ObjetoDeDesenho) recortaCircunferencia((Circunferencia) objetoDeDesenho);
		} else if (objetoDeDesenho instanceof DesenhoComposto) {
			retorno = (ObjetoDeDesenho) recortaDesenhoComposto((DesenhoComposto) objetoDeDesenho);
		} else {
			throw new UnsupportedOperationException(
					"Recorte nao disponivel para o tipo de objeto");
		}
		return retorno;
	}
}
